//
//  SecureManager.m
//  HandPay
//
//  Created by xy on 10-5-7.
//  Copyright 2010 HANDPAY. All rights reserved.
//

#import "SecureManager.h"
#include "des.h"
#include "CUtility.h"
#include <time.h>
#include "HPRsa.h"

#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
#import <Security/Security.h>
#import "ZZTongDefine.h"

const char *rsaModulus = "103977770573549333231156437012845131146128511155452597873662318827602752004483422854282896887871003596639730773110438650359739242827191679615292326989403300690046255733672404239717794786229260570221161206712563608254877713950394646850969034922883687420464616711544390849956836228870744362136696285980592726277";
const char *rsaExmod ="65537";
#define SIZE_BUFFER 1024

void createDesKey(int * randSeed,int * desKey){
	int i;
	unsigned char ct[8];
	unsigned char desKey1[8]={0x68,0x61,0x6e,0x64,0x70,0x61,0x79,0x21};
	unsigned char * rt=NULL;
	
	
	//initseed
	for (i=0; i<16; i++) {
		srand((int)time(0)+i);
		int temp=rand()%0xff;
		randSeed[i]=temp;
	}
	/*randSeed[0]=0xe5;
	randSeed[1]=0x3b;
	randSeed[2]=0x8b;
	randSeed[3]=0x85;
	randSeed[4]=0x28;
	randSeed[5]=0x8b;
	randSeed[6]=0xa0;
	randSeed[7]=0x8e;
	randSeed[8]=0xff;
	randSeed[9]=0x58;
	randSeed[10]=0xbc;
	randSeed[11]=0xb5;
	randSeed[12]=0x23;
	randSeed[13]=0xc9;
	randSeed[14]=0x1e;
	randSeed[15]=0x95;*/
	
    LOG(@"createseed");
	NSString * tems=@"";
	for (i=0; i<8; i++) {
		ct[i]=randSeed[i]^randSeed[i+8];
		tems=[tems stringByAppendingFormat:@"%x ",ct[i]];
	}
    

	LOG(@"createkey:");
	tems=@"";
	rt=Des(desKey1,ct, 1,8,8);
	if (rt) {
		for (i=0; i<8; i++) {
			tems=[tems stringByAppendingFormat:@"%x ",rt[i]];
			desKey[i]=rt[i];
		}
		free(rt);
	}
	
}
int converCtoI(int c){
	if(c>=48 && c<58){
		return c-48;
	}
	else if(c>=65 && c<71){
		return c-65+10;
	}
	else if(c>=97 && c<103){
		return c-97+10;
	}
	return 0;
}
unsigned char * HexTobyte(const char * source,int sourcelen,int * rlen){
	int i=0;
	unsigned char * resultdata=NULL;
	if (!source || sourcelen==0 || sourcelen%2!=0) {
		return NULL;
	}
	resultdata=(unsigned char *)malloc(sizeof(unsigned char)*sourcelen/2);
	* rlen=sourcelen/2;
	for (i=0; i<sourcelen/2; i++) {
		int tempi=converCtoI(source[2*i]);
		resultdata[i]=(tempi<<4)&0xf0;
		resultdata[i]=resultdata[i]+converCtoI(source[2*i+1]);
	}
	return resultdata;
}
char * byteToHex(const unsigned char * source,int sourcelen,int * rlen){
	int i;
	unsigned char ac[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
		'B', 'C', 'D', 'E', 'F' };
	char * resultdata=(char *)malloc(sizeof(char)*(sourcelen*2+1));
	resultdata[sourcelen*2]='\0';
	* rlen=sourcelen*2+1;
	for (i=0; i<sourcelen; i++) {
		resultdata[2*i] = ac[source[i] >> 4 & 0xf];
		resultdata[2*i+1] = ac[source[i] & 0xf];
	}
	return resultdata;
}

@implementation SecureManager
@synthesize overdate;
@synthesize securekey;
@synthesize secureseed;
@synthesize securekeyindex;
@synthesize sessionId;


-(void)CreatNewSeed{
	if (self.securekey==NULL) {
		self.securekey=(int *)malloc(sizeof(int)*8);
	}
	if (self.secureseed==NULL) {
		self.secureseed=(int *)malloc(sizeof(int)*16);
	}
	createDesKey(self.secureseed,self.securekey);
	
	self.overdate=nil;
	self.securekeyindex=nil;
	
}

-(id)init{
    if (self = [super init]) {
		self.overdate=nil;
		self.sessionId=nil;
		self.securekey=NULL;
		self.secureseed=NULL;
		//[self CreatNewSeed];
	}
	return self;
}

-(void)dealloc{
	self.overdate = nil;
	self.sessionId = nil;
	self.securekeyindex = nil;
	
	if (self.securekey) {
		free(self.securekey);
		self.securekey = NULL;
	}
	
	if (self.secureseed) {
		free(self.secureseed);
		self.secureseed = NULL;
	}
	[super dealloc];
}


-(NSString *)NeedCreatSecureKey{
	if (self.overdate==nil && self.securekey!=NULL && self.secureseed!=NULL) {
		int rlen;
		unsigned char tempseed[16];
		for (int i=0; i<16; i++) {
			int temp=self.secureseed[i];
			tempseed[i]=temp;
		}
		char * hex=byteToHex(tempseed,16,&rlen);
		NSString * result=[NSString stringWithUTF8String:hex];
		free(hex);
		
		result=[result stringByAppendingString:@"|"];
		NSDate * date=[NSDate date];
		NSString * datedescr=[date description];
		NSRange range;
		
		//year
		range.location=0;
		range.length=4;
		NSString * tempdescr=[datedescr substringWithRange:range];
		result=[result stringByAppendingString:tempdescr];
		
		//moon
		range.location=5;
		range.length=2;
		tempdescr=[datedescr substringWithRange:range];
		result=[result stringByAppendingString:tempdescr];
		
		//day
		range.location=8;
		range.length=2;
		tempdescr=[datedescr substringWithRange:range];
		result=[result stringByAppendingString:tempdescr];
		
		//hour
		range.location=11;
		range.length=2;
		tempdescr=[datedescr substringWithRange:range];
		result=[result stringByAppendingString:tempdescr];
	
		//minites
		range.location=14;
		range.length=2;
		tempdescr=[datedescr substringWithRange:range];
		result=[result stringByAppendingString:tempdescr];

		//second
		range.location=17;
		range.length=2;
		tempdescr=[datedescr substringWithRange:range];
		result=[result stringByAppendingString:tempdescr];
		
        LOG(@"rsa:%@",result);

		return result;
	}
	return nil;
}


-(void)ReSetSecure:(NSString *)keyindex{
    LOG(@"ReSetSecure::%@",keyindex);
	if (keyindex!=nil) {
		self.securekeyindex=keyindex;
		self.overdate=[NSDate dateWithTimeIntervalSinceNow:60*60*6];
	}
	else {
		[self CreatNewSeed];
	}

}


-(unsigned char *)DesForByte:(const unsigned char* )data withDataLen:(int)datalen withKey:(const unsigned char *)key withflag:(int) flag withlen:(int *)rlen{
	int i=0,desnum=0;
	if (self.securekey==NULL || self.secureseed==NULL) {
		[self CreatNewSeed];
	}
	if (self.overdate!=nil  && flag==1) {
		NSDate * date=[NSDate date];
		if ([self.overdate compare:date]==NSOrderedAscending) {
			[self CreatNewSeed];
		}
	}
	
	unsigned char * tempkey=(unsigned char *)malloc(sizeof(unsigned char)*8);
	if (key!=NULL) {
		for (i=0; i<8; i++) {
			tempkey[i]=key[i];
		}
		//tempkey=(unsigned char *)malloc(sizeof(unsigned char)*8);
	}else {
		for (i=0; i<8; i++) {
			tempkey[i]=self.securekey[i];
		}
	}

	

	desnum=datalen/8;
	unsigned char * result=(unsigned char *)malloc(sizeof(unsigned char)*(datalen + 1));
    
	for (i=0; i<desnum; i++) {
		int j;
		unsigned char temp[8];
		for (j=0; j<8; j++) {
			temp[j]=data[i*8+j];
		}
		unsigned char * tempresult=Des(tempkey, temp, flag,8,8);
		for (j=0; j<8; j++) {
			result[i*8+j]=tempresult[j];
			//printf("%x  ",result[i*8+j]);
		}
		free(tempresult);
	}
    result[datalen] = 0;
	free(tempkey);
	*rlen=datalen;
	return result;
}

-(NSString *)encryptDes:(NSString *)data{
    return [self Des:data withKey:nil withflag:1];
}

-(NSString *)decryptDes:(NSString *)data{
    if (!data) {
        return nil;
    }
    return [self Des:data withKey:nil withflag:0];
}

//-(NSString *)decryptDes:(NSString *)data{
//    CCCryptorStatus ccStatus;
//    uint8_t *bufferPtr = NULL;
//    size_t bufferPtrSize = 0;
//    size_t movedBytes = 0;
//    
//    char srcData[2048] = {0};
//    int inLen = hexEncode((const char*)[data UTF8String], [data length], srcData);
//    
//    bufferPtrSize = (inLen + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1);
//    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
//    memset((void *)bufferPtr, 0x0, bufferPtrSize);
//    ccStatus = CCCrypt(kCCDecrypt,
//                       kCCAlgorithmDES,
//                       kCCOptionECBMode,
//                       self.securekey,
//                       kCCKeySizeDES,
//                       nil,
//                       srcData,
//                       inLen,
//                       (void *)bufferPtr,
//                       bufferPtrSize,
//                       &movedBytes);
//    if (ccStatus == kCCSuccess) {
//
//        NSString* str = [[NSString alloc]initWithBytes:bufferPtr length:movedBytes encoding:NSUTF8StringEncoding];
////        NSString* str = [NSString stringWithUTF8String:(const char*)bufferPtr];
//        return str;
////        return  [NSString stringWithUTF8String:(const char*)bufferPtr];
//    }else{
//        return nil;
//    }
//}

-(NSString *)Des:(NSString * )data withKey:(NSString * )key withflag:(int) flag{

	NSString * rNss=nil;
	int tdd=0;//,i=0;
	
	
	//处理key
	unsigned char * tempkey=NULL;
	if (key) {
		const char * teskey=[key UTF8String];
		int rlen;
		if (strlen(teskey)!=16) {
			return nil;
		}
		tempkey=HexTobyte(teskey,strlen(teskey),&rlen);
	}
	//处理key over
	
	// treat data
	unsigned char * tempdata=NULL;
	const char * tempdatau=[data UTF8String];
	int datalen=strlen(tempdatau);

	if(flag==1){//jiami		
		tdd=datalen%8;
		if (tdd>0) {
			tdd=8-tdd;
		}
		tdd=datalen+tdd;
		tempdata=(unsigned char *)malloc(sizeof(unsigned char)*tdd);
		memset(tempdata, 0, tdd);
		memcpy(tempdata, tempdatau, datalen);
		/*for (i=0; i<tdd; i++) {
			if (i<datalen) {
				tempdata[i]=tempdatau[i];
			}else {
				tempdata[i]=0;
			}	
		}*/
		
	}else {//jiemi
		if (datalen%16!=0) {
			if (tempkey) {
				free(tempkey);
			}
			return nil;
		}
		tempdata=HexTobyte(tempdatau,datalen,&tdd);
		
	}
	// treat data over
	
	unsigned char * result= [self DesForByte:tempdata withDataLen:tdd withKey:tempkey withflag:flag withlen:&tdd];
	if (tempkey) {
		free(tempkey);
	}
	if (tempdata) {
		free(tempdata);
	}
	if (!result) {
		return nil;
	}
	
	if (flag==1) {//jiami
		int rlen;
		char * hexstr=byteToHex(result,tdd,&rlen);
		rNss=[NSString stringWithUTF8String:hexstr];
		free(hexstr);
	}else {//jiemi
        rNss = [NSString stringWithUTF8String:(const char*)result];
//		rNss=[[[NSString alloc] initWithBytes:result length:tdd encoding:NSUTF8StringEncoding] autorelease];
	}
	free(result);

	return rNss;
}

-(NSString *)MD5:(NSString *)data{
	const char *cStr = [data UTF8String];
    unsigned char result[16];
    CC_MD5( cStr, strlen(cStr), result );
    return [NSString stringWithFormat:
            @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
            result[0], result[1], result[2], result[3], 
            result[4], result[5], result[6], result[7],
            result[8], result[9], result[10], result[11],
            result[12], result[13], result[14], result[15]
            ]; 
}
-(NSString *)MAC:(NSString *)data withKey:(NSString *)key{

	const char *cStr = [data UTF8String];
    unsigned char result[16];
	int rlen;
	
    CC_MD5( cStr, strlen(cStr), result );
	
	
	unsigned char * macdata=[self DesForByte:result withDataLen:16 withKey:NULL withflag:1 withlen:&rlen];
	NSString * restr=nil;
	
	if (macdata!=NULL) {
		char * hexstr=byteToHex(macdata,16,&rlen);
		restr=[NSString stringWithUTF8String:(char *)hexstr];
		free(hexstr);
		free(macdata);			
	}
	return restr; 
}

// mcm : arg len change type from 'int' to 'NSUInteger'.
// reason: ready for conversion to 64 bit
-(NSString *)CalcCRC:(const char *)data withlen:(NSUInteger)len
{
	unsigned char result[16];
	int rlen;
	CC_MD5( data, (CC_LONG)len, result ); // mcm: cast value len to CG_LONG
	unsigned char * macdata=[self DesForByte:result withDataLen:16 withKey:NULL withflag:1 withlen:&rlen];
	NSString * restr=nil;
	
	if (macdata!=NULL)
    {
		char * hexstr=byteToHex(macdata,16,&rlen);
		restr=[NSString stringWithUTF8String:(char *)hexstr];
		free(hexstr);
		free(macdata);			
	}
	return restr;
}

-(NSString *)RSA:(NSString *)data{
    /*const char * seedchars=[seed UTF8String];
    int slen=strlen(seedchars);
    unsigned char tmp[512] = {0};
    unsigned int le = 0;
    char *rsaModulus = "103977770573549333231156437012845131146128511155452597873662318827602752004483422854282896887871003596639730773110438650359739242827191679615292326989403300690046255733672404239717794786229260570221161206712563608254877713950394646850969034922883687420464616711544390849956836228870744362136696285980592726277";
    char *rsaExmod ="65537";
    char *ree = (char*)malloc(1024);
    RSA_PublicEncrypt(rsaModulus,rsaExmod,(unsigned char*)seedchars,(unsigned int)slen,tmp,&le);
    int len = hexDecode(tmp,le,ree);
    if (ree) {
        NSString * rsaStr = [[NSString alloc] initWithBytes:ree length:len encoding:NSUTF8StringEncoding];
        NSString* rsa=[@"testrsaid|" stringByAppendingString:rsaStr];
        [rsaStr release];
        [resultd setObject:rsa forKey:HEADER_NAME_KEYEXCHANGE];
        free(ree);
    }*/
    if (!data || [data length] == 0) {
        return nil;
    }
    
    int srclen = [data length];
    unsigned int le = 0;
    const char* src = [data UTF8String];
    unsigned char buffer[SIZE_BUFFER] = {0};
    RSA_PublicEncrypt(rsaModulus, rsaExmod, (unsigned char*)src, srclen, buffer, &le);
    if (le == 0) {
        return nil;
    }
    char result[SIZE_BUFFER] = {0};
    le = hexDecode(buffer, le, result);
    NSString* str = [[NSString alloc] initWithBytes:result length:le encoding:NSUTF8StringEncoding];
    return [str autorelease];
}
@end
